package cn.ys.base.service.impl;

import cn.ys.base.cons.RegisterCons;
import cn.ys.base.service.VerifyCodeService;
import cn.ys.base.util.BussinessException;
import cn.ys.base.util.SendMsg_webchinese;
import cn.ys.base.util.VerifyCodeUtils;
import cn.ys.org.dto.PhoneRegisterDto;
import cn.ys.org.dto.ShopUserCodeDto;
import cn.ys.user.domain.Logininfo;
import cn.ys.user.domain.User;
import cn.ys.user.mapper.LogininfoMapper;
import cn.ys.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceimpl implements VerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;


    @Override
    public String imageCode(String imageCodeKey) throws IOException {
        // 调用工具类获取图形验证码
        String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
        // 将数据存入redis
        redisTemplate.opsForValue().set(imageCodeKey,verifyCode,2, TimeUnit.MINUTES);
        return VerifyCodeUtils.VerifyCode(100,40,verifyCode);
    }

    @Override
    public void smsCode(ShopUserCodeDto dto) {

        if("binder".equals(dto.getType())){
            // 短信发送
            extracted1(dto);
        }else if("register".equals(dto.getType())){
            extracted(dto);
            extracted1(dto);
        }

    }

    // 手机号注册
    @Override
    public void phoneRegister(PhoneRegisterDto dto) {
        // 1.校验参数 dto已做
        // 2.判断手机验证码
        // 通过业务键加手机号在redis中取
        String verification  = (String) redisTemplate.opsForValue().get(String.format(RegisterCons.REGISTER_KEY, dto.getPhone()));
        // 判断是否正确及过期
        if(StringUtils.isBlank(verification) || !dto.getSmsCode().equals(verification)){
            throw new BussinessException("手机验证码无效");
        }
        // 3.判断两次密码是否相同
        if(!dto.getPassword().equals(dto.getPasswordRepeat())){
            throw new BussinessException("两次密码不一致");
        }
        // 4.判断手机号是否注册
        User user = userMapper.findByPhone(dto.getPhone());
        if (user != null) {
            throw new BussinessException("账号以注册，请登录");
        }
        // 4.保存数据
        // 转换为user对象
        user = dto.getUser();
        // 转换成logininfo对象
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);
        logininfo.setType(1);
        logininfo.setDisable(1);
        // 先添加logininfo
        logininfoMapper.add(logininfo);
        // 添加user
        user.setLogininfoId(logininfo.getId());
        userMapper.add(user);
    }

    private void extracted1(ShopUserCodeDto dto) {
        // 4.判断两次发送是否间隔60秒
        Long expire = redisTemplate.getExpire(String.format(RegisterCons.REGISTER_KEY,dto.getPhone()));
        if(expire != null && (expire != -2 || expire > (RegisterCons.TIME-1)*60L)) {
            throw new BussinessException("未间隔60秒请勿重新发送");
        }
        // 5.判断是否需要重置验证码
        String yanZ = (String) redisTemplate.opsForValue().get(String.format(RegisterCons.REGISTER_KEY,dto.getPhone()));
        if(StringUtils.isBlank(yanZ)){
            yanZ = VerifyCodeUtils.generateVerifyCode(4);
        }
        log.info("验证码为：{}",yanZ);
        // 6.将验证码存到redis中
        redisTemplate.opsForValue().set(String.format(RegisterCons.REGISTER_KEY,dto.getPhone()), yanZ, RegisterCons.TIME, TimeUnit.MINUTES);
        // 7.发送短信
        SendMsg_webchinese.send(dto.getPhone(), yanZ);
    }

    private void extracted(ShopUserCodeDto dto) {
        // 1.校验参数 dto中已校验
        // 2.判断图形验证码是否正确和过期
        //2.1通过uuid将图形验证码从redis中取出
        String imageKey = (String) redisTemplate.opsForValue().get(dto.getImageCodeKey());
        if(StringUtils.isBlank(imageKey) || !dto.getImageCodeValue().equalsIgnoreCase(imageKey)){
            throw new BussinessException("图形验证码无效，重新输入");
        }
        // 3.判断手机号是否注册
        User user = userMapper.findByPhone(dto.getPhone());
        if (user != null) {
            throw new BussinessException("账号以注册，请登录");
        }

        // 删除图形验证码
        redisTemplate.delete(dto.getImageCodeKey());
    }
}
